package cn.chiship.framework.business.core.config;

import cn.chiship.framework.common.util.SwaggerUtil;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType;
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
import org.springframework.boot.actuate.endpoint.web.*;
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.util.StringUtils;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.spring.web.plugins.Docket;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/***
 * @author: lijian
 */
@Configuration
@EnableOpenApi
public class Swagger3Config {

	/**
	 * 权限模块
	 */
	private static final String UPMS_CONTROLLER = "cn.chiship.framework.upms.biz.";

	/**
	 * 文档模块
	 */
	private static final String DOC_CONTROLLER = "cn.chiship.framework.docs.biz.";

	/**
	 * 业务模块
	 */
	private static final String BUSINESS_CONTROLLER = "cn.chiship.framework.business.biz.";

	/**
	 * 三方模块
	 */
	private static final String THIRD_CONTROLLER = "cn.chiship.framework.third.biz.";

	@Bean
	public HttpMessageConverter responseBodyConverter() {
		StringHttpMessageConverter converter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
		return converter;
	}

	@Bean
	public Docket createBaseApi() {
		return baseDoctor("2.1.基本模块", UPMS_CONTROLLER + "base.controller");
	}

	@Bean
	public Docket createBase2Api() {
		return baseDoctor("2.2.公共接口", BUSINESS_CONTROLLER + "global");
	}

	@Bean
	public Docket createSystemApi() {
		return baseDoctor("3.1.权限-系统模块", UPMS_CONTROLLER + "system.controller");
	}

	@Bean
	public Docket createUserApi() {
		return baseDoctor("3.2.权限-用户模块", UPMS_CONTROLLER + "user.controller");
	}

	@Bean
	public Docket createDocsApi() {
		return baseDoctor("3.3.文档模块", DOC_CONTROLLER + "controller");
	}

	@Bean
	public Docket createBusinessApi() {
		return baseDoctor("4.1.业务-业务模块", BUSINESS_CONTROLLER + "business.controller");
	}

	@Bean
	public Docket createAllApi() {
		return baseDoctor("5.1.三方-综合模块", THIRD_CONTROLLER + "all.controller");
	}

	@Bean
	public Docket createWxPubApi() {
		return baseDoctor("5.2.三方-微信公众号模块", THIRD_CONTROLLER + "wxpub.controller");
	}

	@Bean
	public Docket createWxMiniApi() {
		return baseDoctor("5.3.1.三方-微信小程序模块", THIRD_CONTROLLER + "wxmini.controller");
	}

	private Docket baseDoctor(String groupName, String apiPath) {
		return SwaggerUtil.buildDocket(groupName, "接口文档", "v1.0", apiPath);
	}

	/**
	 * 增加如下配置可解决Spring Boot 与Swagger 3.0.0 不兼容问题
	 **/
	@Bean
	public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier,
			ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier,
			EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties,
			WebEndpointProperties webEndpointProperties, Environment environment) {
		List<ExposableEndpoint<?>> allEndpoints = new ArrayList();
		Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
		allEndpoints.addAll(webEndpoints);
		allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
		allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
		String basePath = webEndpointProperties.getBasePath();
		EndpointMapping endpointMapping = new EndpointMapping(basePath);
		boolean shouldRegisterLinksMapping = this.shouldRegisterLinksMapping(webEndpointProperties, environment,
				basePath);
		return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes,
				corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath),
				shouldRegisterLinksMapping, null);
	}

	private boolean shouldRegisterLinksMapping(WebEndpointProperties webEndpointProperties, Environment environment,
			String basePath) {
		return webEndpointProperties.getDiscovery().isEnabled() && (StringUtils.hasText(basePath)
				|| ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT));
	}

}
